package com.lianxi.exacl.pdf;

import cn.hutool.core.lang.Console;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.core.util.ZipUtil;
import com.itextpdf.text.Font;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import org.junit.Test;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;


import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class DempPDF {


    public static void main(String[] args) {
        Map<String, String> data = new HashMap();
        data.put("username", "李四");
        data.put("sex", "男");
        data.put("age", "20");
        Map<String, String> map2 = new HashMap();
        Map<String, Object> o = new HashMap();
        o.put("datemap", data);

        DempPDF.pdfout(o);
    }


    @Test
    public void test() {
        // 模板文件路径
        String inputFileName = "D:\\Desktop\\demo.pdf";
        // 生成的文件路径
        String outputFileName = "D:\\Desktop\\demo2.pdf";

        OutputStream os = null;
        PdfStamper ps = null;
        PdfReader reader = null;
        PdfStamper stamper = null;

        try {
            os = new FileOutputStream(new File(outputFileName));
            // 2 读入pdf表单
            reader = new PdfReader(inputFileName);
            // 3 根据表单生成一个新的pdf
            ps = new PdfStamper(reader, os);

            // 4 获取pdf表单
            AcroFields form = ps.getAcroFields();
            // 6查询数据================================================
            Map<String, Object> data = new HashMap<String, Object>();
            data.put("username", "李四");
            data.put("sex", "男");
            data.put("age", "20");
            // 7遍历data 给pdf表单表格赋值
            for (String key : data.keySet()) {
                form.setField(key, data.get(key).toString());
            }

            ps.setFormFlattening(true);
            System.out.println("===============PDF导出成功=============");
        } catch (Exception e) {
            System.out.println("===============PDF导出失败=============");
            e.printStackTrace();
        } finally {
            try {
                ps.close();
                reader.close();
                os.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }


    @Test
    public void test2() {
        // 模板文件路径
        String inputFileName = "D:\\Desktop\\demo.pdf";
        // 生成的文件路径
        String outputFileName = "D:\\Desktop\\jieguo.pdf";

        OutputStream os = null;
        PdfStamper ps = null;
        PdfReader reader = null;
        PdfStamper stamper = null;

        try {
            os = new FileOutputStream(new File(outputFileName));
            // 2 读入pdf表单
            reader = new PdfReader(inputFileName);
            // 3 根据表单生成一个新的pdf
            ps = new PdfStamper(reader, os);
            // 4 获取pdf表单
            AcroFields form = ps.getAcroFields();
            // 5给表单添加中文字体
            BaseFont bf = BaseFont.createFont("D:\\Desktop\\font\\font-awesome\\fonts\\fontawesome-webfont.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            Font font = new Font(bf, 14, Font.NORMAL);
            form.addSubstitutionFont(bf);
            // 6查询数据================================================
            Map<String, Object> data = new HashMap<String, Object>();
            data.put("username", "李四");
            data.put("sex", "28");
            data.put("age", "2021");
//            data.put("month", "09");
//            data.put("day", "23");
//            data.put("userName", "张三");
//            data.put("address", "河南省案发时发放手动阀是的");
            // 7遍历data 给pdf表单表格赋值
            for (String key : data.keySet()) {
                form.setField(key, data.get(key).toString());
            }
            ps.setFormFlattening(true);
            System.out.println("===============PDF导出成功=============");
        } catch (Exception e) {
            System.out.println("===============PDF导出失败=============");
            e.printStackTrace();
        } finally {
            try {
                ps.close();
                reader.close();
                os.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    // 利用模板生成pdf
    public static void pdfout(Map<String, Object> o) {
        // 模板路径
        String templatePath = "D:\\Desktop\\demo.pdf";
        // 生成的新文件路径
        String newPDFPath = "D:\\Desktop\\jieguo.pdf";

        PdfReader reader;
        FileOutputStream out;
        ByteArrayOutputStream bos;
        PdfStamper stamper;
        try {
            BaseFont bf = BaseFont.createFont("D:\\Desktop\\font\\font-awesome\\fonts\\fontawesome-webfont.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            Font FontChinese = new Font(bf, 5, Font.NORMAL);
            out = new FileOutputStream(newPDFPath);// 输出流
            reader = new PdfReader(templatePath);// 读取pdf模板
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();
            //文字类的内容处理
            Map<String, String> datemap = (Map<String, String>) o.get("datemap");
            form.addSubstitutionFont(bf);
            for (String key : datemap.keySet()) {
                String value = datemap.get(key);
                form.setField(key, value);
            }
//            //图片类的内容处理
//            Map<String, String> imgmap = (Map<String, String>) o.get("imgmap");
//            for (String key : imgmap.keySet()) {
//                String value = imgmap.get(key);
//                String imgpath = value;
//                int pageNo = form.getFieldPositions(key).get(0).page;
//                Rectangle signRect = form.getFieldPositions(key).get(0).position;
//                float x = signRect.getLeft();
//                float y = signRect.getBottom();
//                //根据路径读取图片
//                Image image = Image.getInstance(imgpath);
//                //获取图片页面
//                PdfContentByte under = stamper.getOverContent(pageNo);
//                //图片大小自适应
//                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
//                //添加图片
//                image.setAbsolutePosition(x, y);
//                under.addImage(image);
//            }
            stamper.setFormFlattening(true);// 如果为false，生成的PDF文件可以编辑，如果为true，生成的PDF文件不可以编辑
            stamper.close();
            Document doc = new Document();
            Font font = new Font(bf, 32);
            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();
            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
            copy.addPage(importPage);
            doc.close();
        } catch (IOException e) {
            System.out.println(e);
        } catch (DocumentException e) {
            System.out.println(e);
        }

    }



    @Test
    public void test3(){


    }


}


/**
 * ZipUtils
 * 文件压缩工具类
 */

class ZipUtils {

    private static final int BUFFER_SIZE = 2 * 1024;

    /**
     * 压缩成ZIP 方法1
     *
     * @param srcDir           压缩文件夹路径
     * @param out              压缩文件输出流
     * @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构; false:所有文件跑到压缩包根目录下(注意：不保留目录结构可能会出现同名文件,会压缩失败)
     * @throws RuntimeException 压缩失败会抛出运行时异常
     */
    public static void toZip(String srcDir, OutputStream out, boolean KeepDirStructure) throws RuntimeException {

        long start = System.currentTimeMillis();
        ZipOutputStream zos = null;
        try {
            zos = new ZipOutputStream(out);
            File sourceFile = new File(srcDir);
            compress(sourceFile, zos, sourceFile.getName(), KeepDirStructure);
            long end = System.currentTimeMillis();
            Console.log("压缩完成，耗时：" + (end - start) + " ms");
        } catch (Exception e) {
            throw new RuntimeException("zip error from ZipUtils", e);
        } finally {
            if (zos != null) {
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 压缩成ZIP 方法2
     *
     * @param srcFiles 需要压缩的文件列表
     * @param out      压缩文件输出流
     * @throws RuntimeException 压缩失败会抛出运行时异常
     */
    public static void toZip(List<File> srcFiles, OutputStream out) throws RuntimeException {
        long start = System.currentTimeMillis();
        ZipOutputStream zos = null;
        try {
            zos = new ZipOutputStream(out);
            for (File srcFile : srcFiles) {
                byte[] buf = new byte[BUFFER_SIZE];
                zos.putNextEntry(new ZipEntry(srcFile.getName()));
                int len;
                FileInputStream in = new FileInputStream(srcFile);
                while ((len = in.read(buf)) != -1) {
                    zos.write(buf, 0, len);
                }
                zos.closeEntry();
                in.close();
            }
            long end = System.currentTimeMillis();
            System.out.println("压缩完成，耗时：" + (end - start) + " ms");
        } catch (Exception e) {
            throw new RuntimeException("zip error from ZipUtils", e);
        } finally {
            if (zos != null) {
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 递归压缩方法
     *
     * @param sourceFile       源文件
     * @param zos              zip输出流
     * @param name             压缩后的名称
     * @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构; false:所有文件跑到压缩包根目录下(注意：不保留目录结构可能会出现同名文件,会压缩失败)
     * @throws Exception
     */
    private static void compress(File sourceFile, ZipOutputStream zos, String name, boolean KeepDirStructure)
            throws Exception {
        byte[] buf = new byte[BUFFER_SIZE];
        if (sourceFile.isFile()) {
            // 向zip输出流中添加一个zip实体，构造器中name为zip实体的文件的名字
            zos.putNextEntry(new ZipEntry(name));
            // copy文件到zip输出流中
            int len;
            FileInputStream in = new FileInputStream(sourceFile);
            while ((len = in.read(buf)) != -1) {
                zos.write(buf, 0, len);
            }
            // Complete the entry
            zos.closeEntry();
            in.close();
        } else {
            File[] listFiles = sourceFile.listFiles();
            if (listFiles == null || listFiles.length == 0) {
                // 需要保留原来的文件结构时,需要对空文件夹进行处理
                if (KeepDirStructure) {
                    // 空文件夹的处理
                    zos.putNextEntry(new ZipEntry(name + "/"));
                    // 没有文件，不需要文件的copy
                    zos.closeEntry();
                }

            } else {
                for (File file : listFiles) {
                    // 判断是否需要保留原来的文件结构
                    if (KeepDirStructure) {
                        // 注意：file.getName()前面需要带上父文件夹的名字加一斜杠,
                        // 不然最后压缩包中就不能保留原来的文件结构,即：所有文件都跑到压缩包根目录下了
                        compress(file, zos, name + "/" + file.getName(), KeepDirStructure);
                    } else {
                        compress(file, zos, file.getName(), KeepDirStructure);
                    }

                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        /** 测试压缩方法1 */
        /*  FileOutputStream fos1 = new FileOutputStream(new File("D:\\test\\back.zip"));
        ZipUtils.toZip("D:\\test\\back", fos1, true);*/

        // 测试压缩方法2 /*
        List<File> fileList = new ArrayList<>();
        fileList.add(new File("D:\\Desktop\\demo.doc"));
        fileList.add(new File("D:\\Desktop\\demo.pdf"));
        FileOutputStream fos2 = new FileOutputStream(new File("D:\\Desktop\\demo.zip"));
        ZipUtils.toZip(fileList, fos2);

    }
}

